<!-- vue3实现一个通用的右键菜单组件  -->
<template>
  <div ref="containerRef">
    <slot></slot>
    <Teloport to="body">
      <Transition
        @beforeEnter="handleBeforeEnter"
        @enter="handleEnter"
        @afterEnter="handleAfterEnter">
        <div
          class="context-menu"
          v-if="showMenu"
          :style="{ left: x + 'px', top: y + 'px' }">
          <div class="menu-list">
            <div
              v-for="(item, index) in menu"
              :key="item.lable || index"
              @click="handleClick(item)"
              class="menu-item">
              {{ item.lable }}
            </div>
          </div>
        </div>
      </Transition>
    </Teloport>
  </div>
</template>

<script setup lang="ts" name="Contextmenu">
  import { ref, RendererElement } from "vue";
  import { useContextMenu } from "./useContextMenu";

  interface IMenuItem {
    lable: string;
  }

  defineProps({
    menu: {
      type: Array<IMenuItem>,
      default: () => [],
    },
  });

  const containerRef = ref(null);
  const emit = defineEmits(["select"]);
  const { showMenu, x, y } = useContextMenu(containerRef);

  function handleClick(item: IMenuItem) {
    showMenu.value = false;
    emit("select", item);
  }

  function handleBeforeEnter(el: RendererElement) {
    el.style.height = 0;
  }

  function handleEnter(el: RendererElement) {
    el.style.height = "auto";
    const h = el.clientHeight;
    el.style.height = 0 + "px";
    requestAnimationFrame(() => {
      el.style.height = h + "px";
      el.style.transition = "height 0.5s";
    });
  }

  function handleAfterEnter(el: RendererElement) {
    el.style.transition = "none";
  }
</script>

<style scoped lang="scss">
  .context-menu {
    position: absolute;
    .menu-list {
      padding: 0 10px;
      box-shadow: 0 0 2px 2px #f1f1f1;
      background: #fff;
      .menu-item {
        padding: 4px 5px;
        text-align: center;
        cursor: pointer;
        &:hover {
          color: #0073e5;
        }
      }
    }
  }
</style>
